package com.vcs.frm.web.client;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.vcs.frm.domain.Client;
import com.vcs.frm.domain.Employee;
import com.vcs.frm.domain.Jobseeker;
import com.vcs.frm.service.JobseekerService;
import com.vcs.frm.service.client.ClientService;
import com.vcs.frm.service.common.CommonService;
import com.vcs.frm.service.company.EmployeeService;

@Controller(value = "loginController")
@RequestMapping(value = "c")
public class ClientLoginController implements AuthenticationSuccessHandler,
		AuthenticationFailureHandler {

	/* Logger */
	private final Logger log = Logger.getLogger(this.getClass());

	@Autowired
	CommonService commonService;

	@Autowired
	ClientService clientService;

	@Autowired
	JobseekerService jobseekerService;

	@Autowired
	EmployeeService employeeService;

	public void setCommonService(CommonService commonService) {
		this.commonService = commonService;
	}

	public void setClientService(ClientService clientService) {
		this.clientService = clientService;
	}

	public void setJobseekerService(JobseekerService jobseekerService) {
		this.jobseekerService = jobseekerService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}

	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView initClientLoginForm() {

		System.out.println("INSIDE CLIENT LOGIN FORM CONTROLLER GET METHOD");
		ModelAndView mav = new ModelAndView();

		mav.setViewName("clientLogin");
		return mav;
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public ModelAndView processClientLoginForm() {
		log.info("INSIDE CLIENT LOGIN FORM CONTROLLER *POST* METHOD");
		ModelAndView mav = new ModelAndView();

		mav.setViewName("showClientProfile");
		return mav;
	}

	/**
	 * user gets redirected here after his authentication succeeds. Load user's
	 * profile here based on his
	 */
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication auth)
			throws IOException, ServletException {

		log.info("---------------------------------------------------------");

		WebAuthenticationDetails details = (WebAuthenticationDetails) auth
				.getDetails();
		log.info(details.getSessionId());
		log.info("User Logged in from Remote Address : "
				+ details.getRemoteAddress());
		log.info(auth);
		log.info("Credentials : " + auth.getCredentials());
		log.info("Details : " + auth.getDetails());
		log.info("Name : " + auth.getName());
		log.info("Principal : " + auth.getPrincipal());
		log.info("isAuthenticated : " + auth.isAuthenticated());
		log.info("Authorities : " + auth.getAuthorities());

		HttpSession session = request.getSession();
		Enumeration<String> attrs = session.getAttributeNames();
		while (attrs.hasMoreElements()) {
			String element = attrs.nextElement();
			log.info(">>>>>" + element + " : " + session.getAttribute(element));
		}

		// STEP : 1
		Client client = clientService
				.getClientProfileByUsername(auth.getName());

		Jobseeker js = jobseekerService.getJobseekerProfileByUsername(auth
				.getName());

		Employee emp = employeeService.getEmployeeProfileByUsername(auth
				.getName());

		/* set client's profile in session */
		if (null != client) {
			log.info("Got client's profile from DB, setting it in session.");
			if (session.getAttribute("jobseeker") != null) {
				session.removeAttribute("jobseeker");
			}
			if (session.getAttribute("emp") != null) {
				session.removeAttribute("emp");
			}
			session.setAttribute("client", client);
			/* And send user to client's profile home page */
			response.sendRedirect("c/profile");

			// request.getRequestDispatcher("c/profile").forward(request,
			// response);
		} else if (null != js) {
			log.info("Got Jobseeker's profile from DB, setting it in session.");
			if (session.getAttribute("client") != null) {
				session.removeAttribute("client");
			}
			if (session.getAttribute("emp") != null) {
				session.removeAttribute("emp");
			}
			session.setAttribute("jobseeker", js);
			response.sendRedirect("js/profile");
		} else if (null != emp) {
			log.info("Got Employees's profile from DB, setting it in session.");
			if (session.getAttribute("client") != null) {
				session.removeAttribute("client");
			}
			if (session.getAttribute("jobseeker") != null) {
				session.removeAttribute("jobseeker");
			}
			session.setAttribute("emp", emp);
			response.sendRedirect("comp/emp/profile");
		}

		/*
		 * if client and js both are null then it is an error state. It means
		 * that a record is present in the USERS table and USER_ROLES tables but
		 * profile is missing from JOBSEEKERS or CLIENTS table. This should be
		 * investigated from backend.
		 */

		if (client == null && js == null && emp == null) {
			log
					.error("Logged in user's profile is missing in both CLIENTS AND JOBSEEKERS tables.");
			response.sendRedirect("error");
		}

		log.info("---------------------------------------------------------");
	}

	@Override
	public void onAuthenticationFailure(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException exception)
			throws IOException, ServletException {

		log.info("----------------------------------------------------------");
		log.info(":::::User's authentication failed:::::");
		log.info(":::::Remote Ip : " + request.getRemoteAddr());
		log.info(exception.getMessage());
		log.info("----------------------------------------------------------");

		HttpSession session = request.getSession();
		if (session.getAttribute("jobseeker") != null) {
			session.removeAttribute("jobseeker");
		}
		if (session.getAttribute("emp") != null) {
			session.removeAttribute("emp");
		}
		if (session.getAttribute("jobseeker") != null) {
			session.removeAttribute("jobseeker");
		}

		/*
		 * just forward user's request so exception information can be shown on
		 * jsp
		 */
		request.getRequestDispatcher("home").forward(request, response);
	}

}
